package org.jtsmix.mixfile;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * simple database, stores crc id - file name relation
 * <p/>
 * This is used to recover file name from mix archive, because only crc id is
 * saved there.
 *
 * @author ivosh-mint
 */
public class MixDB {
    /**
     * gobal database for Tiberian Sun
     */
    private static final Map<Long, String> globalDB_TS;
    /**
     * global database for Tiberian Dawn / Red Alert
     */
    private static final Map<Long, String> globalDB_TDRA;
    private Map<Long, String> localDB;
    private GameType gameType;
    private static Logger logger;

    // todo user database for his own names

    static {
        logger = Logger.getLogger(MixDB.class.getName());
        BufferedReader br = new BufferedReader(new InputStreamReader(MixDB.class.getResourceAsStream("/globalMixDatabase.dat")));
        globalDB_TS = new HashMap<Long, String>();
        globalDB_TDRA = new HashMap<Long, String>();
        if (br != null) {
            String strLine;
            try {
                while ((strLine = br.readLine()) != null) {
                    for (String s : strLine.split("\0")) {
                        if (s.length() < 1) {
                            continue;
                        }
                        globalDB_TS.put(CRCCounter.getWestwoodCRC(s, GameType.game_ts), s);
                        globalDB_TDRA.put(CRCCounter.getWestwoodCRC(s, GameType.game_ra), s);
                    }
                }
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "Could not initialize global mix database due to I/O failure.", ex);
            }
        }
    }

    /**
     * load local mix database from a stream
     * <p/>
     * Expected format is sequence of file names (ASCII charset), separated by
     * \0 character. File names are not case sensitive. Some text extra may be added,
     * but it can cause lower perfomance, because it will be also indexed as file
     * names.
     *
     * @param is
     */
    public MixDB(InputStream is, GameType gameType) {
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String strLine;
        this.gameType = gameType;
        localDB = new HashMap<Long, String>();
        try {
            while ((strLine = br.readLine()) != null) {
                for (String s : strLine.split("\0")) {
                    if (s.length() < 1) {
                        continue;
                    }
                    localDB.put(CRCCounter.getWestwoodCRC(s, gameType), s);
                }
            }
        } catch (IOException ex) {
            logger.log(Level.SEVERE, "Could not initialize local mix database due to I/O failure.", ex);
        }
    }

    /**
     * search for file name corresponding to given id
     * <p/>
     * Only global mix database is used.
     *
     * @param crcId
     * @return
     */
    public static String getGlobalName(long crcId, GameType gameType) {
        if (gameType == GameType.game_ts) {
            return globalDB_TS.get(crcId);
        } else {
            return globalDB_TDRA.get(crcId);
        }
    }

    /**
     * search for file name corresponding to given id
     * <p/>
     * Both local and global database is used.
     *
     * @param crcId
     * @return
     */
    public String getName(long crcId) {
        String ret = getGlobalName(crcId, gameType);
        if (ret == null) {
            return getLocalName(crcId);
        }
        return ret;
    }

    /**
     * search for file name corresponding to given id
     * <p/>
     * Only local mix database is used.
     *
     * @param crcId
     * @return
     */
    public String getLocalName(long crcId) {
        return localDB.get(crcId);
    }

    /**
     * add new file name to local mix database.dat, included in mix archive
     *
     * @param name file name to add
     */
    public void addLocalName(String name) {
        long crcID = CRCCounter.getWestwoodCRC(name, gameType);
        if (!localDB.containsKey(crcID)) {
            localDB.put(crcID, name);
        }
    }

    /**
     * remove file name from local mix database.dat included in mix archive
     *
     * @param name file name to remove
     */
    public void removeLocalName(String name) {
        long crcID = CRCCounter.getWestwoodCRC(name, gameType);
        if (localDB.containsKey(crcID)) {
            localDB.remove(crcID);
        }
    }

    // TODO user
    public void exportLocalDB(File file) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }


}